//
//  STDSBlendEffect.hpp
//  STDRenderSDK
//
//  Created by 陈学明 on 2023/3/20.
//

#ifndef STDSBlendEffect_hpp
#define STDSBlendEffect_hpp

#include <stdio.h>
#include "STDSBaseEffect.hpp"
#include "STDSBlendType.h"
/// 混合模式效果
class STDSBlendEffect: public STDSBaseEffect {
public:
    STDSBlendEffect() {
        mEffectType = STDSEffectTypeBlend;
    }
    
    ~STDSBlendEffect() {
//        printf("dealloc--STDSBlendEffect\n");
    }
    void initGL() override {
        switch (mBlendType) {
            case STDSBlendTypeNormal:
                mBlendProgram = mContext->getProgram(kShaderSRCBlendNormal);
                break;
            case STDSBlendTypeMultioly:
                mBlendProgram = mContext->getProgram(kShaderSRCBlendMultiply);
                break;
            case STDSBlendTypeScreen:
                mBlendProgram = mContext->getProgram(kShaderSRCBlendSrceen);
                break;
            case STDSBlendTypeOverlay:
                mBlendProgram = mContext->getProgram(kShaderSRCBlendOverlay);
                break;
            case STDSBlendTypeDarken:
                mBlendProgram = mContext->getProgram(kShaderSRCBlendDarken);
                break;
            case STDSBlendTypeLighten:
                mBlendProgram = mContext->getProgram(kShaderSRCBlendLighten);
                break;
            case STDSBlendTypeColorDodge:
                mBlendProgram = mContext->getProgram(kShaderSRCBlendColorDodge);
                break;
            case STDSBlendTypeColorBurn:
                mBlendProgram = mContext->getProgram(kShaderSRCBlendColorBurn);
                break;
            case STDSBlendTypeHardLight:
                mBlendProgram = mContext->getProgram(kShaderSRCBlendHardLight);
                break;
            case STDSBlendTypeSoftLight:
                mBlendProgram = mContext->getProgram(kShaderSRCBlendSoftLight);
                break;
            case STDSBlendTypeDiffrence:
                mBlendProgram = mContext->getProgram(kShaderSRCBlendDifference);
                break;
            case STDSBlendTypeExclusion:
                mBlendProgram = mContext->getProgram(kShaderSRCBlendDifference);
                break;
            case STDSBlendTypeAdd:
                mBlendProgram = mContext->getProgram(kShaderSRCBlendAdd);
                break;
            default:
                break;
        }
    }
    
    void unInitGL() override {
        mSrcTexture = nullptr;
        mDstTexture = nullptr;
        mBlendProgram = nullptr;
    }
    
    void setSrcTex(shared_ptr<STDSTexture> tex) {
        mSrcTexture = tex;
    }
    
    void setDstTex(shared_ptr<STDSTexture> tex) {
        mDstTexture = tex;
    }
    
    void setBlendType(STDSBlendType blend) {
        mBlendType = blend;
    }
    
public:
    void draw() override {
        if (mDstTexture == nullptr || (bool)glIsTexture(mDstTexture->getId()) == false) {
            return;
        }
        if (mSrcTexture == nullptr || (bool)glIsTexture(mSrcTexture->getId()) == false) {
            return;
        }
        if (mBlendProgram == nullptr) {
            return;
        }
        mBlendProgram->use();
        glActiveTexture(GL_TEXTURE0);
        glBindTexture(GL_TEXTURE_2D, mSrcTexture->getId());
        mBlendProgram->setUniform(mBlendProgram->getUniform("uTexture2"), 0);
        
        glActiveTexture(GL_TEXTURE1);
        glBindTexture(GL_TEXTURE_2D, mDstTexture->getId());
        mBlendProgram->setUniform(mBlendProgram->getUniform("uTexture"), 1);
        
        mBlendProgram->setUniform(mBlendProgram->getUniform("uOpacitySRC"), mOpacitySRC);
        mBlendProgram->setUniform(mBlendProgram->getUniform("uOpacityDST"), mOpacityDST);
        mBlendProgram->setUniform(mBlendProgram->getUniform("uParam"), mParam);
        
        mAtbRect.setPosVex(mBlendProgram->getAttrib("aPos"));
        mAtbRect.setPosTex(mBlendProgram->getAttrib("aTexCoord"));
        mAtbRect.draw();
        mBlendProgram->unuse();
    }

private:
    float mCount{10};
    STDSBlendType mBlendType{STDSBlendTypeNormal};
    shared_ptr<STDSTexture> mSrcTexture{nullptr};
    shared_ptr<STDSTexture> mDstTexture{nullptr};
    float mOpacitySRC{1.f};
    float mOpacityDST{1.f};
    float mParam{1.f};
    shared_ptr<STDSShaderProgram> mBlendProgram{nullptr};
};
#endif /* STDSBlendEffect_hpp */
